package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.album.client.TrackInfoFeignClient;
import com.atguigu.tingshu.common.cache.TsCache;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.config.WechatAccountConfig;
import com.atguigu.tingshu.user.factory.PurchaseStrategyFactory;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.user.service.UserPaidTrackService;
import com.atguigu.tingshu.user.strategy.PurchaseStrategy;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.swagger.v3.core.util.Json;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.aspectj.weaver.ast.Var;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Resource
    private PurchaseStrategyFactory purchaseStrategyFactory;

    @Resource
    private WxMaService wxMaService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private KafkaService kafkaService;

    @Resource
    private UserPaidAlbumMapper userPaidAlbumMapper;

    @Resource
    private UserPaidTrackMapper userPaidTrackMapper;

    @Resource
    private UserVipServiceMapper userVipServiceMapper;

    @Resource
    private TrackInfoFeignClient trackInfoFeignClient;

    @Resource
    private UserPaidTrackService userPaidTrackService;

    @Resource
    private VipServiceConfigMapper vipServiceConfigMapper;


    @Override
    public Map<String, String> wxLogin(String code) {
        String openId = null;
        try {
            WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
            openId = sessionInfo.getOpenid();
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }
        //判断当前用户是否是第一次登录
        UserInfo userInfo = this.getOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId, openId));
        //表示是第一次登录
        if (userInfo == null) {
            userInfo = new UserInfo();
            //  赋值用户昵称
            userInfo.setNickname("听友" + System.currentTimeMillis());
            //  赋值用户头像图片
            userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
            //  赋值wxOpenId
            userInfo.setWxOpenId(openId);
            //注册
            this.save(userInfo);
            //消息队列：初始化账户信息
            kafkaService.sendMessage(userInfo.getId().toString(), KafkaConstant.QUEUE_USER_REGISTER);
        }
        //向redis里添加数据，表示登录
        String token = UUID.randomUUID().toString().replaceAll("-", "");
        stringRedisTemplate.opsForValue().set(RedisConstant.USER_LOGIN_KEY_PREFIX + token,
                JSONObject.toJSONString(userInfo),
                RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);
        HashMap<String, String> map = new HashMap<>();
        map.put("token", token);
        return map;
    }

    @Override
    @TsCache(prefix = "userInfoVo:")
    public UserInfoVo getUserInfoVoByUserId(Long userId) {
        //根据用户id查询数据里的数据
        UserInfo userInfo = this.getById(userId);
        //构造返回数据类型
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(userInfo, userInfoVo);
        return userInfoVo;
    }

    @Override
    public void updateUser(UserInfoVo userInfoVo) {
        UserInfo userInfo = new UserInfo();
        userInfo.setId(userInfoVo.getId());
        userInfo.setNickname(userInfoVo.getNickname());
        userInfo.setAvatarUrl(userInfoVo.getAvatarUrl());
        this.updateById(userInfo);
    }

    @Override
    public Map<Long, Integer> userIsPaidTrack(Long userId, Long albumId, List<Long> trackIdList) {
        HashMap<Long, Integer> map = new HashMap<>();
        //根据专辑id和用户id获取是否购买过这张专辑
        UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>()
                .eq(UserPaidAlbum::getUserId, userId)
                .eq(UserPaidAlbum::getAlbumId, albumId));
        if (userPaidAlbum != null) {
            for (Long aLong : trackIdList) {
                map.put(aLong, 1);
            }
            return map;
        }
        List<UserPaidTrack> userPaidTracks = userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>()
                .eq(UserPaidTrack::getUserId, userId)
                .in(UserPaidTrack::getTrackId, trackIdList));
        if (!CollectionUtils.isEmpty(userPaidTracks)) {
            //集合不为空，说明用户购买过这张专辑的声音
            List<Long> trackIds = userPaidTracks.stream().map(UserPaidTrack::getTrackId).toList();
            for (Long trackId : trackIdList) {
                if (trackIds.contains(trackId)) {
                    map.put(trackId, 1);
                } else {
                    map.put(trackId, 0);
                }
            }
            return map;
        }
        for (Long trackId : trackIdList) {
            map.put(trackId, 0);
        }
        return map;
    }

    @Override
    public Boolean isPaidAlbum(Long userId, Long albumId) {
        // 根据用户Id 与专辑Id 查询是否有记录
        Long count = userPaidAlbumMapper.selectCount(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId, userId).eq(UserPaidAlbum::getAlbumId, albumId));
        return count > 0;
    }

    @Override
    public List<Long> findUserPaidTrackList(Long userId, Long albumId) {
        //构造查询条件
        LambdaQueryWrapper<UserPaidTrack> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserPaidTrack::getAlbumId, albumId);
        queryWrapper.eq(UserPaidTrack::getUserId, userId);
        //查询数据
        List<UserPaidTrack> userPaidTracks = userPaidTrackMapper.selectList(queryWrapper);
        //将查询到的数据结果集转换为声音id的集合
        List<Long> list = userPaidTracks.stream().map(UserPaidTrack::getTrackId).toList();
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUserPaid(UserPaidRecordVo userPaidRecordVo) {
        PurchaseStrategy strategy = purchaseStrategyFactory.getStrategy(userPaidRecordVo.getItemType());
        if (strategy==null) {
            throw new GuiguException(ResultCodeEnum.FAIL);
        }
        strategy.purchase(userPaidRecordVo);
    }

    @Override
    public void updateVipExpireStatus() {
        //	获取到当前时间
        //	localDateTime 与 Date 转换
        Instant instant = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant();
        Date date = Date.from(instant);
        LambdaQueryWrapper<UserInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserInfo::getIsVip,1);
        wrapper.select(UserInfo::getId);
        wrapper.lt(UserInfo::getVipExpireTime,date);
        //	查询到当前过期用户列表
        List<UserInfo> userInfoList = this.list(wrapper);
        //	判断当前集合不为空
        if (!CollectionUtils.isEmpty(userInfoList)){
            for (UserInfo userInfo : userInfoList) {
                userInfo.setIsVip(0);
            }
            //	批量更新
            this.saveOrUpdateBatch(userInfoList);
        }
    }
}
